/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.ensisa.sunspot;

import java.util.Enumeration;
import fr.ensisa.sunspot.actor.IActor;
import fr.ensisa.sunspot.event.IEvent;
import java.util.Vector;

/**
 *
 * @author michel
 */
public class ActorManager {

    private IKernel kernel;
    private Vector<IActor> actors;
    private IActor [] actorsToUse;
    private Vector<IEvent> eventQueue;

    public ActorManager (IKernel kernel) {
        this.kernel = kernel;
        this.actors = new Vector<IActor> (5);
        this.eventQueue = new Vector<IEvent> (DEFAULT_EVENT_SIZE);
    }

    public Vector<IActor> getActors () {
        return actors;
    }

    public void addActor (IActor actor) {
        actor.setKernel(kernel);
        actors.addElement(actor);
    }

    public void addAllActors (Vector<IActor> v){
        if (v != null) {
            for (Enumeration<IActor> e = v.elements();e.hasMoreElements();) {
                addActor ((IActor) e.nextElement());
            }
        }
    }

    public void removeAllActors () {
        IActor [] cache = new IActor [actors.size()];
        actors.copyInto(cache);
        for (int i = 0 ; i < cache.length; i++){
            removeActor (cache[i]);
        }
        cache = null;
    }

    public void removeActor (IActor actor) {
        actor.setKernel (null);
        actors.removeElement(actor);
    }

    private void allocActorArray () {
        if (actorsToUse == null || actorsToUse.length != actors.size()) {
            actorsToUse = new IActor [actors.size()];
        }
        actors.copyInto(actorsToUse);
    }

    public void process (long timeStamp){
        allocActorArray ();
        int count=-1;
        Logger.getLogger().infoln ("EvenLoop", "start", null);
        IEvent currentEvent = null;
        eventQueue.removeAllElements();
        do {
            Logger.getLogger().infoln ("EvenLoop", "count", count);
            Logger.getLogger().infoln ("EvenLoop", "currentEvent", currentEvent);
            for (int i=0; i < actorsToUse.length;++i) {
                IActor currentActor = actorsToUse[i];
                Logger.getLogger().infoln ("EvenLoop", "actor["+i+"]", currentActor);
                if (currentActor == null) continue;
                if (! currentActor.isActivated()) continue;
                if (! currentActor.canProcess(currentEvent)) continue;
                switch (currentActor.process(timeStamp, currentEvent)) {
                case IActor.RETURN_GETMYEVENTSANDKILLME:
                	actorsToUse[i] = null;
                    add (eventQueue, currentActor.getGeneratedEvent());
                    merge (eventQueue, currentActor.getGeneratedEvents());
                    break;
                case IActor.RETURN_GETMYEVENTSANDDONTKILLME:
                    add (eventQueue, currentActor.getGeneratedEvent());
                    merge (eventQueue, currentActor.getGeneratedEvents());
                    break;
                case IActor.RETURN_KILLME:
                	actorsToUse[i] = null;
                	break;
                case IActor.RETURN_REMOVEMEFROMTHELIST:
                	this.actors.remove(actorsToUse[i]);
                	actorsToUse[i] = null;
                	break;
                
                }
                    
            }
            ++count;
            if (count >= eventQueue.size()) currentEvent = null;
            else currentEvent = (IEvent) eventQueue.elementAt(count);
        } while (currentEvent != null);
        Logger.getLogger().infoln ("EvenLoop", "end", null);
    }

    private void add (Vector<IEvent> events, IEvent newEvent) {
        if (newEvent == null) return;
        events.addElement(newEvent);
    }

    private void merge(Vector<IEvent> events, Vector<IEvent> newEvents) {
        if (newEvents == null) return;
        events.addAll(newEvents);
    }

    final static int DEFAULT_EVENT_SIZE = 12;
}
